package com.android.jump;

import com.android.jump.jumper.Jumper;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.media.MediaPlayer;
import android.view.KeyEvent;
import android.view.SurfaceHolder;

public class GameThread extends Thread {
    /*
     * State-tracking constants
     */
    public static final int STATE_MENU = 0;
    public static final int STATE_LOSE = 1;
    public static final int STATE_PAUSE = 2;
    public static final int STATE_READY = 3;
    public static final int STATE_RUNNING = 4;
    public static final int STATE_WIN = 5;
    public static final int STATE_HIGHSCORE = 6;
    
    private int mState = STATE_MENU;
    
    private GameView mGameView = null;
    private Background mBackground = null;
    private SurfaceHolder mHolder = null;
    private MainMenu mMenu = null;
    private HighScore mHighScore = null;
    private MediaPlayer  mediaPlayer = null;
    private int mCanvasWidth = 0;
    private int mCanvasHeight = 0;
    
    private Jumper mJumper = null;
    
    private long mLastTime;
    
    private boolean mRun;
    
    
    public GameThread(SurfaceHolder nHolder, GameView nGameView) {
        mHolder = nHolder;
        mGameView = nGameView;
        mLastTime = 0;
        
        mediaPlayer = MediaPlayer.create(mGameView.getContext(), R.drawable.bgm);
        mediaPlayer.setLooping(true);
       // mediaPlayer.start();

        Animation am =new Animation();
        am.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.cloud));
        am.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.cloud3));
        
        Animation de =  new Animation();
        de.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.cloud1));
        de.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.cloud2));
        
        Bitmap bg = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.nbg);
        mBackground = new Background(bg, am, de);
       
        Animation sk = new Animation();
        sk.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.static0));
        sk.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.static1));
        
        Animation sk_r = new Animation();
        sk_r.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.static0_r));
        sk_r.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.static1_r));
        
        Animation dk = new Animation();
        dk.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.dy0));
        dk.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.dy1));
        
        Animation dk_r = new Animation();
        dk_r.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.dy0_r));
        dk_r.addBitmap(BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.dy1_r));
        
        mJumper = new Jumper(sk,sk_r,dk,dk_r);
        // should be done in restore
//        mJumper.setPosition(100.0, 480.0);
//        mJumper.setAcceleration(0.0, 0.0);
        
        Bitmap start = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.start);
        Bitmap start_press = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.start_press);
        Bitmap hs = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.highscore);
        Bitmap hs_press = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.highscore_press);
        MenuItem mnStart = new MenuItem(start_press, start);
        MenuItem mnHighScore = new MenuItem(hs, hs_press);
        
        Bitmap mainBG = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.main_bg);

        mMenu = new MainMenu(mainBG, mnStart, mnHighScore);
        
        Bitmap nums[] = new Bitmap[10];
        nums[0] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num0);
        nums[1] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num1);
        nums[2] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num2);
        nums[3] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num3);
        nums[4] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num4);
        nums[5] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num5);
        nums[6] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num6);
        nums[7] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num7);
        nums[8] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num8);
        nums[9] = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.num9);
        
        Bitmap gold = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.gold_n);
        Bitmap sliver = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.sliver);
        Bitmap brone = BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.brone);
        mHighScore = new HighScore(nGameView, BitmapFactory.decodeResource(mGameView.getResources(), R.drawable.hs_bg),
                nums, gold, sliver, brone);
    }
    
    public void setState(int nState) {
        if (nState == STATE_RUNNING)
            mFirstTimeRunning = true;
        ChangeState();
        mState = nState;
    }
    
    public void setRunning(boolean b) {
        mRun = b;
    }
    
    public void setSurfaceSize(int width, int height) {
        // synchronized to make sure these all change atomically
        synchronized (mHolder) {
            mCanvasWidth = width;
            mCanvasHeight = height;

            // don't forget to resize the background image
            //mBackgroundImage = mBackgroundImage.createScaledBitmap(
            //       mBackgroundImage, width, height, true);
        }
    }
    
    boolean mFirstTimeRunning = true;
    @Override
    public void run() {
        while (mRun) {
            Canvas c = null;
            try {
                c = mHolder.lockCanvas(null);
                synchronized (mHolder) {
                    if (mState == STATE_RUNNING) {
                            if (mFirstTimeRunning) {
                            	
                            	mediaPlayer.start();
                                mJumper.restore();
                                mBackground.restore();
                                mLastTime = 0;
                                mFirstTimeRunning = false;
                            }
                        if (bTouchDown) {
                            if (mTouchX < mJumper.getPositionX() + mJumper.getArea().getR()) {
                                mJumper.setFacingLeft(false);
                                mNeedMove = -1;
                            }
                            else if (mTouchX > mJumper.getPositionX() + mJumper.getWidth()){
                                mJumper.setFacingLeft(true);
                                mNeedMove = 1;
                            }
                            else if (mTouchY > mJumper.getPositionY()){
                                mNeedJump++;
                            }
                            bTouchDown = false;
                        }
                        if (bTouchUp) {
                            StopJumper();
                            bTouchUp = false;
                        }
                        updatePhysics();
                        doDraw(c);
                    }
                    else if (mState == STATE_MENU) {
                    	if (bTouchDown){
                    		mMenu.update((int)mTouchX, (int)mTouchY);
                    		mMenu.doDraw(c,0);
                    		bTouchDown = false;
                    	}
                    	else if (bTouchUp) {
                            mMenu.update((int)mTouchX, (int)mTouchY);
                            mMenu.doDraw(c,1);
                            if (mMenu.isClickStart()) {
                                setState(STATE_RUNNING);
                            }
                            else if (mMenu.isClickHighScore()) {
                                mMenu.restore();
                                setState(STATE_HIGHSCORE);
                            }
                            bTouchUp = false;
                        }
                    	 mMenu.doDraw(c,2);
                    }
                    else if (mState == STATE_HIGHSCORE) {
                    	mediaPlayer.pause();
                        mHighScore.doDraw(c);
                        if (bTouchUp) {
                            setState(STATE_MENU);
                        }
                    }
                }
            }
            catch (Exception e) {
            	e.printStackTrace();
            }
            finally {
                // do this in a finally so that if an exception is thrown
                // during the above, we don't leave the Surface in an
                // inconsistent state
                if (c != null) {
                    mHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
    
    private void doDraw(Canvas canvas) {
        mBackground.doDraw(canvas);
        if (mJumper.isFacingLeft()) {
            if (mJumper.isFlying())
                mJumper.setFlyani(0);
            else
                mJumper.setNorani(0);
        }
        else {
            if (mJumper.isFlying())
                mJumper.setFlyani(1);
            else
                mJumper.setNorani(1);
        }
        mJumper.doDraw(canvas);
    }
    
    private void updatePhysics() {
        long now = System.currentTimeMillis();
        if (mLastTime == 0) {
            mLastTime = now;
        }
        
        if (mNeedJump == 1) {
            mJumper.startJump();
        	mNeedJump++;
        }
        
        // speed up~
        double elapsed = (now - mLastTime) / 250.0;
        
        // test move
        if (mNeedMove == -1) {
            mJumper.setVelocity(-30.0+mJumper.getVelocityX(), mJumper.getVelocityY());
        }
        else if(mNeedMove == 1) {
            mJumper.setVelocity(30.0+mJumper.getVelocityX(), mJumper.getVelocityY());
        }
        else {
            mJumper.setVelocity(0.0, mJumper.getVelocityY());
        }
        
        mBackground.updatePhysics(mJumper, elapsed);
        mBackground.Cloudfall(1);
        
        if (mJumper.getPositionX() + mJumper.getArea().getR() > 320) {
            mJumper.setPosition(0, mJumper.getPositionY());
        }
        else if (mJumper.getPositionX() < 0 - 100) {
            mJumper.setPosition(320 - 100, mJumper.getPositionY());
        }
        
        if (mJumper.getPositionY() < 240 && mJumper.getVelocityY() < 0) {
        	mBackground.Update(240 - (int)mJumper.getPositionY());
        	mJumper.setPosition(mJumper.getPositionX(), 240);
        	
        }
        // game lose
//        if (mJumper.getPositionY() > 480.0 && mJumper.getVelocityY() > 0.0) {
//            // sub some velocity
//            mJumper.setVelocity(0.0, -200.0);
//        }
        if (mJumper.getPositionY() > 480.0 && mJumper.getVelocityY() > 0.0) {
            mBackground.saveHighScore(mGameView);
            setState(STATE_HIGHSCORE);
        }
        
        mLastTime = now;
    }
    
    private int mNeedMove = 0;
    private int mNeedJump = 0;
    
    public void OnSpaceKeyUp() {
        mNeedJump++;
        mJumper.setFlyani(1);
    }
    
    public void MoveJumper(int key) {
        if (key == KeyEvent.KEYCODE_DPAD_LEFT) {
            mJumper.setFacingLeft(false);
            mNeedMove = -1;
        }
        else {
            mNeedMove = 1;
            mJumper.setFacingLeft(true);
        }
    }
    
    public void StopJumper() {
        mNeedMove = 0;
    }
    
    boolean bTouchDown = false;
    boolean bTouchUp = false;
    float mTouchX = 0;
    float mTouchY = 0;
    public void OnTouchDown(float x, float y) {
        bTouchDown = true;
        mTouchX = x;
        mTouchY = y;
    }
    
    public void OnTouchUp(float x, float y) {
        bTouchUp = true;
        mTouchX = x;
        mTouchY = y;
    }
    
    private void ChangeState() {
        bTouchUp = false;
        bTouchDown = false;
        mNeedMove = 0;
        mNeedJump = 0;
    }
    
    public void stopMusic()
    {
    	mediaPlayer.stop();
    }
}
